#!/usr/bin/perl -w

use utf8;
use strict;
use JSON;
use Encode;
use Data::Dumper;
use Net::FTP;
use threads;
use threads::shared;

#ftp config
#{
#	"upload":{
#		"interval":3000,
#		"config":[
#					{
#						"ip":"192.169.77.171",
#						"port":21121,
#						"user":"zwftp",
#						"pass":"shandongzhaowuftppassword",
#						"local":"/sdzw/netspider/spider/upload/baidutieba",
#						"remote":"tieba",
#						"ext":"zip"
#					}
#				]
#		},
#	"download":{
#	}
#}

my $config_ = shift @ARGV;

if(! defined($config_)){
	print "Need a config file ... ftp.pl <config-file>\n";
	exit(1);
}

###read config
my $config_str;

open my $config_fh, '<', $config_ or die "open config $config_ failed!";

while(<$config_fh>){
	$config_str .= "$_";
}

close $config_fh;

#status
my $upload_count:shared = 0, my $download_count:shared = 0;
my $count = 0;


##decode
my $json = JSON->new->utf8->decode($config_str);

##get upload config
my $interval_up;

my $upload_json = $json->{'upload'};

$interval_up = $upload_json->{'interval'};

my $upload = $upload_json->{'config'};

sub upload_func {
	my ($interval, $upload) = @_;
	
	my $ip 		= $upload->{'ip'};
	my $port 	= $upload->{'port'};
	my $user 	= $upload->{'user'};
	my $pass 	= $upload->{'pass'};
	my $local 	= $upload->{'local'};
	my $remote 	= $upload->{'remote'};
	my @extname	= split /\s+/, $upload->{'ext'};

	#create remote
	while(1){
		my $ftp_ = Net::FTP->new(
				$ip,
				Port => $port,
			);

		if(! defined($ftp_)){
			print("Can not connect $ip : $port\n");
			next;
		}

		if(! $ftp_->login($user, $pass)) {
			print "Can not login $ip : $port\n";
			next;	
		}

		$ftp_->mkdir($remote);

		$ftp_->quit;

		last;
	}
	
	while(1){
		my $ftp = Net::FTP->new(
			$ip,
			Port => $port,
		);

		if(! defined($ftp)){
			print("Can not connect $ip : $port\n");
			sleep($interval);
			redo;
		}

		if(! $ftp->login($user, $pass)) {
			print "Can not login $ip : $port\n";
			sleep($interval);
			redo;
		}

		$ftp->binary;

		my @filelist = find($local, $remote, \@extname);

		foreach(@filelist){
			if($ftp->put(${$_}[0], ${$_}[1])){
				unlink ${$_}[0];
				$upload_count++;
			}
		}		

		$ftp->quit;

		sleep($interval);
	}	
}



foreach(@{$upload}){
	my $up_th = threads->create(\&upload_func, $interval_up, $_);

	$count++;

	$up_th->detach();
}

print "upload [$count] thread\n";

##get download config
my $interval_dl;

my $download_json = $json->{'download'};

$interval_dl = $download_json->{'interval'};

my $download = $download_json->{'config'};

sub download_func {
	my ($interval, $download) = @_;
	
	my $ip 		= $download->{'ip'};
	my $port 	= $download->{'port'};
	my $user 	= $download->{'user'};
	my $pass 	= $download->{'pass'};
	my $local 	= $download->{'local'};
	my $remote 	= $download->{'remote'};
	my @extname	= split /\s+/, $download->{'ext'};

	my $localf;
	
	while(1){
		my $ftp = Net::FTP->new(
			$ip,
			Port => $port,
		);

		$download_count++;

		if(! defined($ftp)){
			print("Can not connect $ip : $port\n");
			sleep($interval);
			redo;
		}

		if(! $ftp->login($user, $pass)) {
			print "Can not login $ip : $port\n";
			sleep($interval);
			redo;
		}

		$ftp->binary;

		my $filelist = $ftp->ls($remote);

		if(defined($filelist)){
			foreach(@{$filelist}){
				$localf = "$local/".get_name($_);
				if($ftp->get($_, $localf)){
					$ftp->delete($_);
					$download_count++;
				}
			}
		}else{
			sleep($interval);
			redo;
		}
		
		$ftp->quit;

		sleep($interval);
	}	
}

$count = 0;

foreach (@{$download}){
	my $dl_th = threads->create(\&download_func, $interval_dl, $_);

	$count++;

	$dl_th->detach();
}

print "download [$count] thread\n";

##main thread
while(1){
	my ($sec,$M,$H,$d,$m,$y,$wday,$yday,$isdst) = localtime;

	printf "Time::%04d-%02d-%02d %02d:%02d [download -> %08d] [upload -> %08d]\n", 
			$y + 1900, $m + 1, $d, $H, $M, $download_count, $upload_count;

	sleep(2);
}



#######################################################
sub find {
	my ($local_, $remote_, $extlist) = @_;

	opendir my $local, $local_ or return ();

	my @filelist, my $localf, my $remotef;

	foreach (readdir $local) {
		next if $_ =~ /^\./;
		if(ext_check($_, $extlist)){
			$localf = "$local_/$_";
			$remotef = "$remote_/$_";
			push @filelist, [($localf, $remotef)];
		}
	}

	closedir $local;

	return @filelist;
}

sub ext_check{
	my ($name, $exts) = @_;

	foreach(@{$exts}) {
		my $regex = "^.*\\.$_\\z";

		if($name =~ /$regex/i){
			return 1;
		}
	}

	return 0;
}

sub get_name {
	my $file = shift @_;

	if($file =~ /\/(.*)/){
		return $1;
	}else {
		return $file;
	}
}




